package com.qkun.library.widget;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.ColorInt;
import androidx.annotation.ColorRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.StringRes;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.core.content.ContextCompat;
import androidx.core.graphics.drawable.DrawableCompat;

import com.qkun.library.R;
import com.qkun.library.base.BaseActivity;
import com.qkun.library.base.FullTransparentActivity;
import com.qkun.library.base.TagActivity;
import com.qkun.library.utils.ActivityManager;
import com.qkun.library.utils.DrawableUtils;
import com.qkun.library.utils.MyLog;
import com.qkun.library.utils.Utils;

import java.lang.ref.WeakReference;

/**
 * @author qinkun
 * @date 6/1 0001 22:10
 * @description TODO: 通过wrap适配自定义view以及各种style
 */
public class BottomDialog {

    private static final String TAG = "BottomDialog";

    protected static final int DURATION = 290;

    private final Context mContext;
    private WeakReference<BaseActivity> mActivityRef;
    private View mContentView;
    private View mDialogContentPanel;
    private TextView mTvMsg;
    private FrameLayout mFlCustomPanel;
    private View mLine;
    private LinearLayout mLlButton;
    private OnCancelListener mOnCancelListener;
    private boolean mCancelable;
    private boolean mIsShowing;
    private String mTag;
    private ActivityManager.ActivityLifecycleCallback mActivityLifecycleCallback;

    private BottomDialog(@NonNull Context context) {
        mContext = Utils.requireNonNull(context);
        if (context instanceof BaseActivity) {
            bindActivity((BaseActivity) context);
        }
        init();
    }

    public static BottomDialog make(@NonNull Context context) {
        return new BottomDialog(context);
    }

    private void init() {
        mContentView = View.inflate(mContext, R.layout.layout_bottom_dialog, null);
        mDialogContentPanel = mContentView.findViewById(R.id.dialog_content_panel);
        mTvMsg = mContentView.findViewById(R.id.tv_message);
        mFlCustomPanel = mContentView.findViewById(R.id.fl_custom_panel);
        mLine = mContentView.findViewById(R.id.v_line);
        mLlButton = mContentView.findViewById(R.id.ll_button);

        Resources resources = mContext.getResources();
        DisplayMetrics displayMetrics = resources.getDisplayMetrics();
        int contentWidth = Math.min(displayMetrics.widthPixels, displayMetrics.heightPixels);
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(contentWidth, ViewGroup.LayoutParams.WRAP_CONTENT);
        if (resources.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
            layoutParams.gravity = Gravity.CENTER;
        } else {
            layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
        }
        mDialogContentPanel.setLayoutParams(layoutParams);

        mContentView.findViewById(R.id.dialog_root_view).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mIsShowing && mCancelable) {
                    if (Utils.nonNull(mOnCancelListener)) {
                        mOnCancelListener.onCancel(BottomDialog.this);
                    }
                    dismiss();
                }
            }
        });
    }

    public boolean isShowing() {
        return mIsShowing;
    }

    private void bindActivity(@NonNull BaseActivity activity) {
        mActivityRef = new WeakReference<>(Utils.requireNonNull(activity));
    }

    public BaseActivity getActivity() {
        return Utils.nonNull(mActivityRef) ? mActivityRef.get() : null;
    }

    public void dismiss() {
        mIsShowing = false;
        if (Utils.nonNull(mActivityRef) && Utils.nonNull(mActivityRef.get())) {
            mContentView.post(new Runnable() {
                @Override
                public void run() {
                    final Activity activity = mActivityRef.get();
                    if (Utils.nonNull(activity)) {
                        Utils.disableTouch(activity, true);
                        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mDialogContentPanel,
                                View.TRANSLATION_Y, 0, (mContentView.getHeight() - mDialogContentPanel.getTop()));
                        objectAnimator.setDuration(DURATION);
                        objectAnimator.addListener(new AnimatorListenerAdapter() {
                            @Override
                            public void onAnimationEnd(Animator animation) {
                                super.onAnimationEnd(animation);
                                View rootView = activity.getWindow().getDecorView();
                                if (rootView instanceof ViewGroup) {
                                    ViewGroup rootLayout = (ViewGroup) rootView;
                                    rootLayout.removeView(mContentView);
                                }
                                Utils.disableTouch(activity, false);
                                if (Utils.nonNull(mActivityLifecycleCallback)) {
                                    activity.finish();
                                }
                            }
                        });
                        objectAnimator.start();
                    }
                }
            });
        }
    }

    public void show(String tag) {
        if (Utils.nonNull(mActivityRef) && Utils.nonNull(mActivityRef.get())) {
            View rootView = mActivityRef.get().getWindow().getDecorView();
            if (rootView instanceof ViewGroup) {
                ViewGroup rootLayout = (ViewGroup) rootView;
                mDialogContentPanel.setAlpha(0.0f);
                rootLayout.addView(mContentView);
                mContentView.post(new Runnable() {
                    @Override
                    public void run() {
                        final Activity activity = mActivityRef.get();
                        if (Utils.nonNull(activity)) {
                            Utils.disableTouch(activity, true);
                            ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mDialogContentPanel,
                                    View.TRANSLATION_Y, mContentView.getHeight() - mDialogContentPanel.getTop(), 0);
                            objectAnimator.setDuration(DURATION);
                            objectAnimator.addListener(new AnimatorListenerAdapter() {
                                @Override
                                public void onAnimationStart(Animator animation) {
                                    super.onAnimationStart(animation);
                                    mDialogContentPanel.setAlpha(1.0f);
                                }

                                @Override
                                public void onAnimationEnd(Animator animation) {
                                    super.onAnimationEnd(animation);
                                    Utils.disableTouch(activity, false);
                                    mIsShowing = true;
                                }
                            });
                            objectAnimator.start();
                        }
                    }
                });
            }
        } else if (Utils.nonNull(tag)) {
            mTag = tag;
            ActivityManager.getInstance().addActivityLifecycleCallback(mActivityLifecycleCallback = new ActivityManager.ActivityLifecycleCallback() {
                @Override
                public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
                    super.onActivityCreated(activity, savedInstanceState);
                    if (activity instanceof BottomDialogActivity) {
                        BottomDialogActivity bottomDialogActivity = (BottomDialogActivity) activity;
                        if (bottomDialogActivity.equalsTag(mTag)) {
                            bindActivity(bottomDialogActivity);
                            show();
                        }
                    }
                }

                @Override
                public void onActivityDestroyed(@NonNull Activity activity) {
                    super.onActivityDestroyed(activity);
                    if (activity instanceof BottomDialogActivity) {
                        BottomDialogActivity bottomDialogActivity = (BottomDialogActivity) activity;
                        if (bottomDialogActivity.equalsTag(mTag)) {
                            mActivityRef = null;
                            mActivityLifecycleCallback = null;
                        }
                    }
                }
            });
            Intent intent = new Intent(mContext, BottomDialogActivity.class);
            intent.putExtra(TagActivity.DATA_TAG, tag);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            mContext.startActivity(intent);
        } else {
            MyLog.e(new IllegalArgumentException("Tag cannot be null for non baseActivity!!!"));
        }
    }

    public void show() {
        show(TAG);
    }

    private void adjustCustomPanelVisibility(boolean visible) {
        if (visible) {
            if (mTvMsg.getVisibility() != View.GONE) {
                mTvMsg.setVisibility(View.GONE);
            }
            if (mFlCustomPanel.getVisibility() != View.VISIBLE) {
                mFlCustomPanel.setVisibility(View.VISIBLE);
            }
        } else {
            if (mFlCustomPanel.getVisibility() != View.GONE) {
                mFlCustomPanel.setVisibility(View.GONE);
            }
            if (mTvMsg.getVisibility() != View.VISIBLE) {
                mTvMsg.setVisibility(View.VISIBLE);
            }
        }
    }

    public BottomDialog setCustomView(@LayoutRes int layoutResId) {
        return setCustomView(layoutResId, null);
    }

    public BottomDialog setCustomView(@LayoutRes int layoutResId, OnCustomViewInitCallback callback) {
        if (layoutResId != 0) {
            mFlCustomPanel.removeAllViews();
            View view = LayoutInflater.from(mContext).inflate(layoutResId, mFlCustomPanel, true);
            if (Utils.nonNull(callback)) {
                callback.onInit(view);
            }
            adjustCustomPanelVisibility(true);
        }
        return this;
    }

    public BottomDialog setCustomView(View view) {
        if (Utils.nonNull(view) && Utils.isNull(view.getParent())) {
            mFlCustomPanel.removeAllViews();
            mFlCustomPanel.addView(view);
            adjustCustomPanelVisibility(true);
        }
        return this;
    }

    public BottomDialog setCustomView(View view, ViewGroup.LayoutParams params) {
        if (Utils.nonNull(view) && Utils.isNull(view.getParent()) && Utils.nonNull(params)) {
            mFlCustomPanel.removeAllViews();
            mFlCustomPanel.addView(view, params);
            adjustCustomPanelVisibility(true);
        }
        return this;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public BottomDialog setIcon(@DrawableRes int iconRes, @ColorRes int tintColorRes) {
        return setIcon(ContextCompat.getDrawable(mContext, iconRes),
                ContextCompat.getColor(mContext, tintColorRes));
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public BottomDialog setIcon(Drawable icon, @ColorInt int tintColor) {
        Utils.requireNonNull(icon);
        Drawable wrapDrawable = DrawableCompat.wrap(icon);
        wrapDrawable.setTint(tintColor);
        return setIcon(wrapDrawable);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public BottomDialog setIcon(Drawable icon, ColorStateList tint) {
        Utils.requireNonNull(icon);
        Drawable wrapDrawable = DrawableCompat.wrap(icon);
        wrapDrawable.setTintList(tint);
        return setIcon(wrapDrawable);
    }

    public BottomDialog setIcon(Drawable icon) {
        Utils.requireNonNull(icon);
        if (icon.getBounds().isEmpty()) {
            icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
        }
        mTvMsg.setCompoundDrawables(null, icon, null, null);
        adjustCustomPanelVisibility(false);
        return this;
    }

    public BottomDialog setIcon(@DrawableRes int iconRes) {
        return setIcon(ContextCompat.getDrawable(mContext, iconRes));
    }

    public BottomDialog setMessage(CharSequence msg) {
        mTvMsg.setText(msg);
        adjustCustomPanelVisibility(false);
        return this;
    }

    public BottomDialog setMessage(@StringRes int resId) {
        mTvMsg.setText(resId);
        adjustCustomPanelVisibility(false);
        return this;
    }

    private BottomDialog addButton(DialogButton button, @NonNull CharSequence text,
                                   @ColorInt int textColor, OnDialogClickListener onDialogClickListener) {
        if (mLlButton.getVisibility() != View.VISIBLE) {
            mLine.setVisibility(View.VISIBLE);
            mLlButton.setVisibility(View.VISIBLE);
        }
        final int N = mLlButton.getChildCount();
        if (N > 0) {
            View view = new View(mContext);
            view.setBackgroundResource(R.color.colorDivider);
            mLlButton.addView(view, mContext.getResources().getDimensionPixelSize(R.dimen.lineThickness), ViewGroup.LayoutParams.MATCH_PARENT);
        }

        button.setWhich(N / 2);
        button.setTextColor(textColor);
        button.setText(text);
        mLlButton.addView(button);
        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) button.getLayoutParams();
        if (Utils.nonNull(layoutParams)) {
            layoutParams.width = 0;
            layoutParams.weight = 1.0f;
            button.setLayoutParams(layoutParams);
        }
        button.bindDialog(this, onDialogClickListener);
        return this;
    }

    public BottomDialog addButton(@NonNull CharSequence text, @ColorInt int textColor, OnDialogClickListener onDialogClickListener) {
        return addButton(new DialogButton(mContext), text, textColor, onDialogClickListener);
    }

    public BottomDialog addButton(@StringRes int textResId, @ColorInt int textColor, OnDialogClickListener onDialogClickListener) {
        return addButton(mContext.getResources().getString(textResId), textColor, onDialogClickListener);
    }

    public BottomDialog addButton(@NonNull CharSequence text, OnDialogClickListener onDialogClickListener) {
        return addButton(text, ContextCompat.getColor(mContext, R.color.colorPrimary), onDialogClickListener);
    }

    public BottomDialog addButton(@StringRes int textResId, OnDialogClickListener onDialogClickListener) {
        return addButton(mContext.getResources().getString(textResId), onDialogClickListener);
    }

    public BottomDialog addDismissButton(@NonNull CharSequence text, @ColorInt int textColor, OnDialogClickListener onDialogClickListener) {
        return addButton(new DialogDismissButton(mContext), text, textColor, onDialogClickListener);
    }

    public BottomDialog addDismissButton(@StringRes int textResId, @ColorInt int textColor, OnDialogClickListener onDialogClickListener) {
        return addDismissButton(mContext.getResources().getString(textResId), textColor, onDialogClickListener);
    }

    public BottomDialog addDismissButton(@NonNull CharSequence text, OnDialogClickListener onDialogClickListener) {
        return addDismissButton(text, ContextCompat.getColor(mContext, R.color.colorGray6), onDialogClickListener);
    }

    public BottomDialog addDismissButton(@StringRes int textResId, OnDialogClickListener onDialogClickListener) {
        return addDismissButton(mContext.getResources().getString(textResId), onDialogClickListener);
    }

    public BottomDialog addSureButton(@ColorInt int textColor, OnDialogClickListener onDialogClickListener) {
        return addButton(R.string.sure, textColor, onDialogClickListener);
    }

    public BottomDialog addSureButton(OnDialogClickListener onDialogClickListener) {
        return addSureButton(ContextCompat.getColor(mContext, R.color.colorPrimary), onDialogClickListener);
    }

    public BottomDialog addSureDismissButton(@ColorInt int textColor, OnDialogClickListener onDialogClickListener) {
        return addDismissButton(R.string.sure, textColor, onDialogClickListener);
    }

    public BottomDialog addSureDismissButton(OnDialogClickListener onDialogClickListener) {
        return addSureDismissButton(ContextCompat.getColor(mContext, R.color.colorPrimary), onDialogClickListener);
    }

    public BottomDialog clearAllButton() {
        if (mLlButton.getVisibility() != View.GONE) {
            mLine.setVisibility(View.GONE);
            mLlButton.setVisibility(View.GONE);
        }
        mLlButton.removeAllViews();
        return this;
    }

    public BottomDialog canCancel(boolean cancelable) {
        mCancelable = cancelable;
        return this;
    }

    public BottomDialog setCancelListener(@Nullable OnCancelListener onCancelListener) {
        mOnCancelListener = onCancelListener;
        if (Utils.nonNull(onCancelListener)) {
            canCancel(true);
        }
        return this;
    }

    public View getContentView() {
        return mContentView;
    }

    public interface OnCancelListener {
        void onCancel(BottomDialog dialog);
    }

    public interface OnCustomViewInitCallback {
        void onInit(View view);
    }

    public interface OnDialogClickListener {
        /**
         * @param dialog
         * @param which  对应添加的 Button 的位置，从 0 开始
         */
        void onClick(BottomDialog dialog, int which);
    }

    static class DialogDismissButton extends DialogButton {

        DialogDismissButton(@NonNull Context context) {
            super(context);
        }

        @Override
        public void onClick(View v) {
            super.onClick(v);
            mDialog.dismiss();
        }
    }

    static class DialogButton extends AppCompatTextView implements View.OnClickListener {

        protected BottomDialog mDialog;
        protected OnDialogClickListener mOnDialogClickListener;
        protected int mWhich;

        DialogButton(@NonNull Context context) {
            super(context);
            init();
        }

        private void init() {
            setClickable(true);
            setFocusable(true);
            setGravity(Gravity.CENTER);
            setBackground(DrawableUtils.getDrawableOfSelectableItemBackground(false));
            setTextSize(TypedValue.COMPLEX_UNIT_PX, getResources().getDimensionPixelSize(R.dimen.buttonTextSize));
            int padding = getResources().getDimensionPixelSize(R.dimen.content_margin);
            setPadding(padding, padding, padding, padding);
            //粗体
            getPaint().setFakeBoldText(true);
            setOnClickListener(this);
        }

        private void setWhich(int which) {
            this.mWhich = which;
        }

        private void bindDialog(BottomDialog dialog, OnDialogClickListener onDialogClickListener) {
            this.mDialog = dialog;
            this.mOnDialogClickListener = onDialogClickListener;
        }

        @Override
        public void onClick(View v) {
            if (Utils.nonNull(mDialog) && Utils.nonNull(mOnDialogClickListener)) {
                mOnDialogClickListener.onClick(mDialog, mWhich);
            }
        }
    }

    /**
     * @hide
     */
    public static class BottomDialogActivity extends FullTransparentActivity {
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }

        @Override
        public void onBackPressed() {
            //禁用返回键
//            super.onBackPressed();
        }
    }
}
